#include "async_logger/logger.hpp"
#include "async_logger/log_level.hpp"
#include "async_logger/log_module.hpp"
#include "async_logger/log_manager.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <iomanip>
#include <filesystem>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <queue>
#include <nlohmann/json.hpp>

class Logger {
public:
    Logger() : logLevel(LogLevel::INFO) {}

    void log(LogLevel level, const std::string& message) {
        if (level >= logLevel) {
            std::lock_guard<std::mutex> lock(mutex);
            logQueue.push(formatMessage(level, message));
            cv.notify_one();
        }
    }

    void setLogLevel(LogLevel level) {
        logLevel = level;
    }

    void startLoggingThread(const std::string& logDir) {
        loggingThread = std::thread(&Logger::processLogQueue, this, logDir);
    }

    void stopLoggingThread() {
        {
            std::lock_guard<std::mutex> lock(mutex);
            stopThread = true;
        }
        cv.notify_one();
        loggingThread.join();
    }

private:
    LogLevel logLevel;
    std::mutex mutex;
    std::condition_variable cv;
    std::queue<std::string> logQueue;
    std::thread loggingThread;
    bool stopThread = false;

    std::string formatMessage(LogLevel level, const std::string& message) {
        auto now = std::chrono::system_clock::now();
        std::time_t nowTime = std::chrono::system_clock::to_time_t(now);
        std::ostringstream oss;
        oss << std::put_time(std::localtime(&nowTime), "%Y-%m-%d %H:%M:%S") << " [" << logLevelToString(level) << "] " << message;
        return oss.str();
    }

    std::string logLevelToString(LogLevel level) {
        switch (level) {
            case LogLevel::DEBUG: return "DEBUG";
            case LogLevel::INFO: return "INFO";
            case LogLevel::WARNING: return "WARNING";
            case LogLevel::ERROR: return "ERROR";
            default: return "UNKNOWN";
        }
    }

    void processLogQueue(const std::string& logDir) {
        while (true) {
            std::unique_lock<std::mutex> lock(mutex);
            cv.wait(lock, [this] { return !logQueue.empty() || stopThread; });

            while (!logQueue.empty()) {
                std::string logMessage = logQueue.front();
                logQueue.pop();
                writeLogToFile(logDir, logMessage);
            }

            if (stopThread) break;
        }
    }

    void writeLogToFile(const std::string& logDir, const std::string& message) {
        // Implement log writing logic with rolling and date-based organization
        // This is a placeholder for the actual implementation
        std::ofstream logFile(logDir + "/log.txt", std::ios::app);
        if (logFile.is_open()) {
            logFile << message << std::endl;
        }
    }
};